package generator.code;

import com.sun.javadoc.PackageDoc;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Method;

import junit.framework.TestSuite;

public class PackageTestSuiteGenerator {

	public void startClassTestSuite(final String outputDIR,
			final PackageDoc[] pkgNames, final String suiteName) {
        
		String fileName = suiteName + ".java";
        File file = new File(outputDIR, fileName);
        BufferedWriter out;

        if (file.exists()) {
            file.delete();
        }

        try {
            out = new BufferedWriter(new FileWriter(file, true));
            out.newLine();
            out.write("/**");
            out.newLine();
            out.write("* Generated by PackageTestSuiteGenerator.\n");
            out.write("* Created on Febrary 2010 by Pablo Sortino <psortino@gmail.com>\n");
            out.write("*/\n\n");
            out.write("import junit.framework.TestCase;\n");
            out.write("import junit.framework.TestSuite;\n");
            out.write("import junit.extensions.TestSetup;\n");
            out.write("import java.io.File;\n");
            out.write("import java.io.IOException;\n");
            out.write("import java.io.FileNotFoundException;\n");
            out.write("import java.io.FileReader;\n");
            out.write("import java.io.BufferedReader;\n");
            out.write("import java.lang.reflect.Method;\n");
            out.write("import java.util.ArrayList;\n");
            out.write("import java.util.Iterator;\n");

            /*for (int i = 0; i < pkgNames.length; i++) {
                if (!pkgNames[i].toString().equals("")) {
                    out.write("import " + pkgNames[i].toString() + ".*;\n");
                }
            }*/
            out.newLine();
            out.newLine();
            
            out.write("//Test suite for the complete package.\n");
            out.write("public final class " + suiteName + " {\n\n");
            
            out.write("\t//Notifies if excluded file of failed test cases exits.\n");
            out.write("\tpublic static boolean excludeFileExists = false;\n\n");
 
            out.write("\t//A variable to keep count of successful test cases.\n");
            out.write("\tpublic static int totalTestCases = 0;\n\n");
            
            out.write("\t//List with all the classes to test\n");
            out.write("\tprivate static ArrayList<String> classesList;\n\n");
            
            out.newLine();
            
            out.write("\t//Private Constructor of the test suite class.\n");
            out.write("\tprivate " + suiteName + "() {\n");
            out.write("\t}\n\n");
            
            out.write("\t/**\n");
            out.write("\t* Set-Up method for the test suite.\n");
            out.write("\t* @return Returns the test suite set-up.\n");
            out.write("\t**/\n");
            out.write("\tpublic static TestSetup suite() {\n");
            out.write("\t\tTestSuite suite = new TestSuite(\"All Packages\");\n");
            
            out.write("\t\tclassesList = readClassesFile(\"" + DocletTestGenerator.classListFilename  + "\");\n");
            
            out.write("\t\tfor (Iterator<String> iterator = classesList.iterator(); iterator.hasNext();) {\n");
            out.write("\t\t\tString className = (String) iterator.next();\n");
            out.write("\t\t\ttry {\n");
            out.write("\t\t\t\tClass<? extends TestCase> classToTest = (Class<? extends TestCase>) Class.forName(className);\n");
            out.write("\t\t\t\tSystem.out.println(\"Adding class \" + classToTest.getName());\n");
            out.write("\t\t\t\t//suite.addTestSuite(classToTest);\n");
            out.write("\t\t\t\tMethod mainMethod = classToTest.getMethod(\"suite\");\n");
            out.write("\t\t\t\tObject o = mainMethod.invoke(null);\n");
            out.write("\t\t\t\tif (o instanceof TestSuite) {\n");
            out.write("\t\t\t\t\tTestSuite tsuite = (TestSuite) o;\n");
            out.write("\t\t\t\t\tfor (int i = 0; i < tsuite.countTestCases()	; i++) {\n");
            out.write("\t\t\t\t\tjunit.framework.Test t = tsuite.testAt(i);\n");
            out.write("\t\t\t\t\tsuite.addTest(t);\n");
            out.write("\t\t\t\t}\n");
            out.write("\t\t\t}\n");
            
            out.write("\t\t\t} catch (ClassNotFoundException cnfe) {\n");
            out.write("\t\t\t\tSystem.out.println(\"Error: Can not load class \" + className);\n");
            out.write("\t\t\t\tcnfe.printStackTrace();\n");
            out.write("\t\t\t} catch (Throwable t) {\n");
            out.write("\t\t\t\tSystem.out.println(\"Error: \" + t.getMessage());\n");
            out.write("\t\t\t\tt.printStackTrace();\n");
            out.write("\t\t\t}\n");
            out.write("\t\t}\n");
            
            out.write("      TestSetup wrapper = new TestSetup(suite) {");
            out.newLine();
            out.newLine();
            out.write("          protected void setUp() {");
            out.newLine();
            out.write("/*\n");
            out.write("              File failedXMLDataFile = new File(");
            out.newLine();
            out.write("              \"" + outputDIR + "\""
                + ", \"failedData.xml\");");
            out.newLine();
            out.write("              File logFile = new File(\"" + outputDIR
                + "\", \"TestFailure.log\");");
            out.newLine();
            out.newLine();
            out.write("              if (logFile.exists()) {");
            out.newLine();
            out.write("                  logFile.delete();");
            out.newLine();
            out.write("                  try {");
            out.newLine();
            out.write("                      //log.createFailedTestLog(\""
                + outputDIR + "\");");
            out.newLine();
            out.write("                  } catch (Exception e) {");
            out.newLine();
            out.write("                      e.printStackTrace();");
            out.newLine();
            out.write("                  }");
            out.newLine();
            out.write("              }");
            out.newLine();
            out.newLine();
            out.write("              if (failedXMLDataFile.exists()) {");
            out.newLine();
            out.write("                  excludeFileExists = true;");
            out.newLine();
            out.write("              } else if ("
                + "!failedXMLDataFile.exists()) {");
            out.newLine();
            out.write("                  try {");
            out.newLine();
            out.write("                      //log.createFailedXMLDataFile(\""
                + outputDIR + "\");");
            out.newLine();
            out.write("                  } catch (Exception e) {");
            out.newLine();
            out.write("                      e.printStackTrace();");
            out.newLine();
            out.write("                  }");
            out.newLine();
            
            out.write("              }");
            out.newLine();
            out.write("*/\n");
            out.write("          }");
            out.newLine(); out.newLine();
            out.write("//Wrap-Up method for the test suite.");

            out.newLine();
            out.write("          protected void tearDown() {");
            out.newLine();
            out.write("/*\n");
            out.write("              File logFile = new File(\"" + outputDIR
                + "\", \"TestSuccess.log\");");
            out.newLine();
            out.newLine();
            out.write("              try {");
            out.newLine();
            out.write("                      BufferedWriter out = new"
                + " BufferedWriter(new"); out.newLine();
            out.write("                         FileWriter(logFile, true));");
            out.newLine();
            out.write("                      out.newLine();");
            out.newLine();
            out.write("                      out.write(\"Total test cases"
                + " executed: \" + totalTestCases);");
            out.newLine();
            out.write("                      out.newLine();");
            out.newLine();
            out.write("                      out.newLine();");
            out.newLine();
            out.write("                      out.flush();");
            out.newLine();
            out.write("                      out.close();");
            out.newLine();
            out.write("              } catch (IOException e) {");
            out.newLine();
            out.write("                   e.printStackTrace();");
            out.newLine();
            out.write("              }");
            out.newLine(); out.newLine();
            out.write("            if (!excludeFileExists) {");
            out.newLine();
            out.write("              try {");
            out.newLine();
            out.write("                  //log.endFailedXMLDataFile(\""
                + outputDIR + "\");"); out.newLine();
            out.write("                  excludeFileExists = true;");
            out.newLine();
            out.write("              } catch (Exception e) {");
            out.newLine();
            out.write("                   e.printStackTrace();");
            out.newLine();
            out.write("              }");
            out.newLine();
            out.write("            }");
            out.newLine();
            out.write("*/\n");
            out.write("          }");
            out.newLine();
            out.write("      };");
            out.newLine();
            out.newLine();
            out.write("      return wrapper;");
            out.newLine();
            out.write("  }");
            out.newLine(); out.newLine();
            out.write("/**"); out.newLine();
            out.write("* Main method of the test suite.");
            out.newLine(); out.newLine();
            out.write("* @param args"); out.newLine();
            out.write("*            Stores arguments to main method");
            out.newLine(); out.write("*/");
            out.newLine();
            out.write("  public static void main(final String[] args) {");
            out.newLine();
            out.write("    // Begin method testsuite.main");
            out.newLine();
            out.write("    junit.textui.TestRunner.run(suite());");
            out.newLine();
            out.write("    // End method testsuite.main");
            out.newLine();
            out.write("  }\n");
            
            /*
            out.newLine();
            out.write("private static ArrayList<String> readClassesFile(String filename) {\n");
			out.write("	ArrayList<String> list = new ArrayList<String>();\n");
			out.write("BufferedReader bufferedReader = null;\n");
			out.write("try {\n");
			out.write("// Construct the BufferedReader object\n");
			out.write("bufferedReader = new BufferedReader(new FileReader(filename));\n");
			out.write("String line = null;\n");
			out.write("while ((line = bufferedReader.readLine()) != null) {\n");
			out.write("if (line != null && !line.isEmpty() && !line.contains(\"#\") ) {\n");
			out.write("list.add(line.trim()+\"Test\");\n");
			out.write("}\n");
			out.write("}\n");
			out.write("} catch (FileNotFoundException ex) {\n");
			out.write("ex.printStackTrace();\n");
			out.write("} catch (IOException ex) {\n");
			out.write("ex.printStackTrace();\n");
			out.write("} finally {\n");
			out.write("// Close the BufferedReader\n");
			out.write("try {\n");
			out.write("if (bufferedReader != null) {\n");
			out.write("bufferedReader.close();\n");
			out.write("}\n");
			out.write("} catch (IOException ex) {\n");
			out.write("ex.printStackTrace();\n");
			out.write("}\n");
			out.write("}\n");
			out.write("return list;\n");
            out.write("}"); out.newLine();*/
            
            
            out.newLine();
            out.write("\tprivate static ArrayList<String> readClassesFile(String filename) {\n");
			out.write("\t\tArrayList<String> list = new ArrayList<String>();\n");
			out.write("\t\tBufferedReader bufferedReader = null;\n");
			out.write("\t\ttry {\n");
			out.write("\t\t\t// Construct the BufferedReader object\n");
			out.write("\t\t\tbufferedReader = new BufferedReader(new FileReader(new File(\""+outputDIR+"\", filename)));\n");
			out.write("\t\t\tString line = null;\n");
			out.write("\t\t\twhile ((line = bufferedReader.readLine()) != null) {\n");
			out.write("\t\t\t\tif (line != null && (line.length() > 0) && !line.contains(\"#\") ) {\n");
			out.write("\t\t\t\t\tlist.add(line.trim());\n");
			out.write("\t\t\t\t}\n");
			out.write("\t\t\t}\n");
			out.write("\t\t} catch (FileNotFoundException ex) {\n");
			out.write("\t\t\tex.printStackTrace();\n");
			out.write("\t\t} catch (IOException ex) {\n");
			out.write("\t\t\tex.printStackTrace();\n");
			out.write("\t\t} finally {\n");
			out.write("\t\t\t// Close the BufferedReader\n");
			out.write("\t\t\ttry {\n");
			out.write("\t\t\t\tif (bufferedReader != null) {\n");
			out.write("\t\t\t\t\tbufferedReader.close();\n");
			out.write("\t\t\t\t}\n");
			out.write("\t\t\t} catch (IOException ex) {\n");
			out.write("\t\t\t\tex.printStackTrace();\n");
			out.write("\t\t\t}\n");
			out.write("\t\t}\n");
			out.write("\t\treturn list;\n");
            out.write("\t}");
            out.newLine();
            out.newLine();
            
            
            out.write("}"); out.newLine();
            
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
	}
}